"""
@-*- coding: utf-8 -*-
@ python: 3.12.3
@ 创建者: JacksonCode
@ 创建时间: 2025-11-06
@ 描述: JWT工具类
"""
import datetime
from functools import wraps
from flask import current_app, request, jsonify
from flask_jwt_extended import (
    create_access_token, create_refresh_token,
    jwt_required, get_jwt_identity, get_jwt
)
from app import db
from app.models import User


class JWTUtils:
    """JWT工具类"""
    
    @staticmethod
    def generate_tokens(user):
        """生成访问令牌和刷新令牌
        
        Args:
            user: 用户对象
            
        Returns:
            dict: 包含access_token和refresh_token的字典
        """
        # 创建访问令牌
        access_token = create_access_token(
            identity=user.id,
            additional_claims={
                'email': user.email,
                'is_admin': user.is_admin
            }
        )
        
        # 创建刷新令牌
        refresh_token = create_refresh_token(identity=user.id)
        
        # 获取过期时间（秒）
        expires_in_seconds = 0
        if 'JWT_ACCESS_TOKEN_EXPIRES' in current_app.config:
            expires_delta = current_app.config['JWT_ACCESS_TOKEN_EXPIRES']
            if isinstance(expires_delta, datetime.timedelta):
                expires_in_seconds = int(expires_delta.total_seconds())
        
        return {
            'access_token': access_token,
            'refresh_token': refresh_token,
            'token_type': 'Bearer',
            'expires_in': expires_in_seconds
        }
    
    @staticmethod
    def get_current_user_id():
        """获取当前用户ID"""
        try:
            return get_jwt_identity()
        except:
            return None
    
    @staticmethod
    def get_current_user():
        """获取当前用户对象"""
        try:
            user_id = get_jwt_identity()
            if user_id:
                return User.query.get(user_id)
            return None
        except:
            return None
    
    @staticmethod
    def is_current_user_admin():
        """检查当前用户是否是管理员"""
        try:
            claims = get_jwt()
            return claims.get('is_admin', False)
        except:
            return False
    
    @staticmethod
    def revoke_token():
        """撤销令牌（将令牌加入黑名单）"""
        try:
            jti = get_jwt()['jti']
            # 这里可以将jti添加到Redis黑名单或数据库中
            # 简化实现，实际应用中应该使用Redis
            return True
        except:
            return False


def create_token_response(user, message="登录成功"):
    """创建标准的令牌响应
    
    Args:
        user: 用户对象
        message: 响应消息
        
    Returns:
        dict: 标准API响应
    """
    tokens = JWTUtils.generate_tokens(user)
    
    return {
        "code": 200,
        "message": message,
        "data": {
            "user": {
                "id": user.id,
                "username": user.username,
                "email": user.email,
                "is_admin": user.is_admin,
                "created_at": user.created_at.isoformat() if user.created_at else None
            },
            "tokens": tokens
        }
    }


def refresh_token_response():
    """刷新令牌响应
    
    Returns:
        dict: 标准API响应
    """
    try:
        current_user_id = get_jwt_identity()
        user = User.query.get(current_user_id)
        
        if not user:
            return {
                "code": 404,
                "message": "用户不存在",
                "data": None
            }
        
        return create_token_response(user, "令牌刷新成功")
    
    except Exception as e:
        return {
            "code": 401,
            "message": "令牌刷新失败",
            "data": None
        }


def token_required(f):
    """JWT令牌验证装饰器"""
    @wraps(f)
    def decorated_function(*args, **kwargs):
        try:
            jwt_required()(lambda: None)()
            return f(*args, **kwargs)
        except Exception as e:
            return jsonify({
                "code": 401,
                "message": "令牌验证失败",
                "data": None
            }), 401
    
    return decorated_function


def admin_required(f):
    """管理员权限验证装饰器"""
    @wraps(f)
    def decorated_function(*args, **kwargs):
        try:
            jwt_required()(lambda: None)()
            
            if not JWTUtils.is_current_user_admin():
                return jsonify({
                    "code": 403,
                    "message": "需要管理员权限",
                    "data": None
                }), 403
                
            return f(*args, **kwargs)
        except Exception as e:
            return jsonify({
                "code": 401,
                "message": "令牌验证失败",
                "data": None
            }), 401
    
    return decorated_function


def self_or_admin_required(f):
    """用户本人或管理员权限验证装饰器"""
    @wraps(f)
    def decorated_function(*args, **kwargs):
        try:
            jwt_required()(lambda: None)()
            current_user_id = JWTUtils.get_current_user_id()
            
            # 检查是否是管理员或操作自己的资源
            target_user_id = kwargs.get('user_id') or request.view_args.get('user_id')
            
            if not JWTUtils.is_current_user_admin() and current_user_id != target_user_id:
                return jsonify({
                    "code": 403,
                    "message": "权限不足",
                    "data": None
                }), 403
                
            return f(*args, **kwargs)
        except Exception as e:
            return jsonify({
                "code": 401,
                "message": "令牌验证失败",
                "data": None
            }), 401
    
    return decorated_function